package xpem

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"strings"
)

func chunkSplit(s string, chunkSize int, end string) string {
	if chunkSize <= 0 {
		return s
	}
	var b strings.Builder
	for i := 0; i < len(s); i += chunkSize {
		endIdx := i + chunkSize
		if endIdx > len(s) {
			endIdx = len(s)
		}
		b.WriteString(s[i:endIdx])
		b.WriteString(end)
	}
	return b.String()
}

func F单独解析公钥方法(base64Key string) (publicKey *rsa.PublicKey, err error) {
	if strings.Contains(base64Key, "BEGIN PUBLIC KEY") {
		return DecodePublicKey([]byte(base64Key))
	}
	formattedKey := chunkSplit(base64Key, 64, "\n")
	pemData := fmt.Sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", formattedKey)
	return DecodePublicKey([]byte(pemData))
}

func DecodePublicKey(pemContent []byte) (publicKey *rsa.PublicKey, err error) {

	block, _ := pem.Decode(pemContent)
	if block == nil {
		return nil, fmt.Errorf("pem.Decode(%s)：pemContent decode error", pemContent)
	}
	switch block.Type {
	case "CERTIFICATE":
		pubKeyCert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("x509.ParseCertificate(%s)：%w", pemContent, err)
		}
		pubKey, ok := pubKeyCert.PublicKey.(*rsa.PublicKey)
		if !ok {
			return nil, fmt.Errorf("公钥证书提取公钥出错 [%s]", pemContent)
		}
		publicKey = pubKey
	case "PUBLIC KEY":
		pub, err := x509.ParsePKIXPublicKey(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("x509.ParsePKIXPublicKey(%s),err:%w", pemContent, err)
		}
		pubKey, ok := pub.(*rsa.PublicKey)
		if !ok {
			return nil, fmt.Errorf("公钥解析出错 [%s]", pemContent)
		}
		publicKey = pubKey
	case "RSA PUBLIC KEY":
		pubKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("x509.ParsePKCS1PublicKey(%s)：%w", pemContent, err)
		}
		publicKey = pubKey
	}
	return publicKey, nil
}

func F通用解析私钥(base64Key string) (*rsa.PrivateKey, error) {
	if strings.Contains(base64Key, "BEGIN PRIVATE KEY") {
		return DecodePrivateKey([]byte(base64Key))
	}
	formattedKey := chunkSplit(base64Key, 64, "\n")
	pemData := fmt.Sprintf("-----BEGIN PRIVATE KEY-----\n%s\n-----END PRIVATE KEY-----", formattedKey)
	return DecodePrivateKey([]byte(pemData))
}

func DecodePrivateKey(pemContent []byte) (privateKey *rsa.PrivateKey, err error) {
	block, _ := pem.Decode(pemContent)
	if block == nil {
		return nil, fmt.Errorf("pem.Decode(%s)：pemContent decode error", pemContent)
	}
	privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		pk8, err := x509.ParsePKCS8PrivateKey(block.Bytes)
		if err != nil {
			return nil, fmt.Errorf("私钥解析出错 [%s]", pemContent)
		}
		var ok bool
		privateKey, ok = pk8.(*rsa.PrivateKey)
		if !ok {
			return nil, fmt.Errorf("私钥解析出错 [%s]", pemContent)
		}
	}
	return privateKey, nil
}
